/***********************************************************************************************************************
 * ############################################# Application AdewebLite #############################################
 * AdewebLite Android est une application permettant de consulter des emplois du temps fournis par l'université UHP
 * avec ou sans connexion internet (informations gardées en mémoire à chaque synchronisation). Et utilisant la web
 * API ADE pour collecter les données.
 * @author Andrianjafintrimo Victor, Zanette Sébastien
 * 
 * Basée sur l'application du même nom, utilisant le flux RSS (données à traiter), de :
 * @author Schnell Michaël, Zanette Sébastien
 * **********************************************************************************************************************
 */

package fr.ul.ade.prime.model;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import fr.ul.ade.prime.analyzer.ContainerData;
import fr.ul.ade.prime.analyzer.FeedAnalyzer;
import fr.ul.ade.prime.analyzer.FeedConnection;
import fr.ul.ade.prime.analyzer.FeedLesson;
import fr.ul.ade.prime.analyzer.FeedResourceEtud;
import fr.ul.ade.prime.database.Database;
import fr.ul.ade.prime.exception.AAAException;
import fr.ul.ade.prime.exception.AAAInternalException;
import fr.ul.ade.prime.exception.EmptyFieldException;
import fr.ul.ade.prime.exception.InvalidValueException;
import fr.ul.ade.prime.ui.MyApplication;

/**
 * Structure pour un emploi du temps.
 * Un emploi du temps connait une liste de cours.
 * Contient un ensemble de fonctions permettant de contrôler les informations fournis par l'utilisateur lors de la création d'un emploi du temps
 * et d'initialiser la contruction des cours.
 * @author Zanette Sébastien
 * @author Andrianjafintrimo Victor
 */
public class Schedule implements Iterable<Lesson>, Parcelable {
	
	private static final String TAG = "Schedule" ; //$NON-NLS-1$

	public static final int NOTIFY_TRUE  = 1 ;
	public static final int NOTIFY_FALSE = 0 ;

	public static final String RESOURCE_SEPARATOR = "|" ; //$NON-NLS-1$

	private static final int NAME_MAX_LENGTH = 50 ;

	private static final String RESSOURCE_FORMAT  = "[0-9]+" ; //$NON-NLS-1$
	private static final String RESSOURCES_FORMAT = 
			String.format("%1$s([ ]*\\|[ ]*%1$s)*", RESSOURCE_FORMAT) ; //$NON-NLS-1$

	private static final String STRING_DISPLAY_FORMAT = "--------------------" + //$NON-NLS-1$
			"\nId: %s\nNom : '%s'\n" + //$NON-NLS-1$
			"ProjectID : '%s'\nRessources : '%s'\nNuméro étudiant : '%s'\nPériode : '%s'\nDer modif : '%s'\n" + //$NON-NLS-1$
			"Crée le : '%s'\nEtat : '%s'\nNotif : '%s'--------------------" ; //$NON-NLS-1$

	protected long id ;
	protected Project project ;
	protected String name ;
	protected String resources ;
	protected int period ;
	protected String lastUpdate ;
	protected ScheduleState state ;
	protected String created ;
	protected Lessons lessons ;
	protected String studentNum;
	protected String ressStudentNum;
	protected ArrayList<StudentNumber> studentNumList;
	protected boolean notify ;

	/**
	 * Initialisation d'un emploi du temps avec les champs données en paamètre.
	 * 
	 * @param id identifiant unique dans la base de données
	 * @param projectId Projet AdeWeb identifiant une partie de l'Université de Lorraine
	 * @param name Nom de l'emploi du temps donnée pa l'utilisateur
	 * @param ressources Numéro de ressources donnée par l'utilisateur
	 * @param period Période pour laquelle synchroniser l'emploi du temps
	 * @param lastModif Date de dernière synchronisation de l'emploi du temps
	 * @param state Statut de synchronisation (non synchro, en attente de synchro, en synchronisation, synchronisé)
	 * @param created Date de crétion de l'emploi du temps
	 * @param studentNum Numéro(s) étudiant donnée(s) par l'utilisateur
	 */
	public Schedule(long id, Project project, String name, String ressources, 
			int period, String lastModif, ScheduleState state, String created, 
			String studentNum) {
		super() ;
		this.id = id ;
		this.project = project ;
		this.name = name.trim() ;
		this.resources = ressources.trim() ;
		this.period = period;
		this.lastUpdate = lastModif;
		this.state = state;
		this.created = created;
		this.lessons = new Lessons() ;
		this.studentNum = studentNum ;
		this.ressStudentNum = "" ; //$NON-NLS-1$
		this.studentNumList = new ArrayList<StudentNumber>() ;               
	}
	
	public Schedule(Schedule source) {
		this(source.getId(), source.getProject(), source.getName(),
				source.getResources(), source.getPeriod(), source.getLastUpdate(),
				source.getState(), source.getCreated(), source.getStudentNum()) ;
	}// Schedule(Schedule)

	/**
	 * Initialisation d'un emploi du temps avec les champs données en paamètre.
	 * 
	 * @param projectId Projet AdeWeb identifiant une partie de l'Université de Lorraine
	 * @param name Nom de l'emploi du temps donnée pa l'utilisateur
	 * @param ressources Numéro de ressources donnée par l'utilisateur
	 * @param period Période pour laquelle synchroniser l'emploi du temps
	 * @param lastModif Date de dernière synchronisation de l'emploi du temps
	 * @param state Statut de synchronisation (non synchro, en attente de synchro, en synchronisation, synchronisé)
	 * @param created Date de crétion de l'emploi du temps
	 * @param studentNum Numéro(s) étudiant donnée(s) par l'utilisateur
	 */
	public Schedule(Project project, String name, String ressources, int period, 
			String lastModif, ScheduleState state, String created, String studentNum) {
		this(-1, project, name, ressources, period, lastModif, state, created, studentNum) ;             
	}
	
	public Schedule(String name, Resource[] resources, int period, Project project) {
		this.id = 0 ;
		this.project = project ;
		this.name = name.trim() ;
		this.studentNum = "" ; //$NON-NLS-1$
		this.setResources(resources) ;
		this.period = period;
		this.lastUpdate = new SimpleDateFormat("yyyy/MM/dd HH:mm") //$NON-NLS-1$
			.format(new Date()) ;
		this.state = ScheduleState.OTHER ;
		this.created = this.lastUpdate ;
		this.lessons = new Lessons() ;
		this.ressStudentNum = "" ; //$NON-NLS-1$
		this.studentNumList = new ArrayList<StudentNumber>() ; 
	}

	/**
	 * Initialisation d'un emploi du temps avec les valeurs par défaut
	 */
	public Schedule() {
		this(-1, null, "", "", 0, "", ScheduleState.OTHER, "","") ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
	}

	/**
	 * @param source
	 */
	public Schedule(Parcel in) {
//		this() ;
		ClassLoader classLoader = this.getClass().getClassLoader() ;
		
		this.id = in.readLong() ;
		this.project = in.readParcelable(classLoader) ;
		this.name = in.readString() ;
		this.resources = in.readString() ;
		this.period = in.readInt() ;
		this.lastUpdate = in.readString() ;
		this.state = in.readParcelable(classLoader) ;
		this.created = in.readString() ;
		this.lessons = in.readParcelable(classLoader) ;
		this.studentNum = in.readString() ;
		this.ressStudentNum = in.readString() ;
		this.studentNumList = new ArrayList<StudentNumber>() ;
		in.readTypedList(this.studentNumList, StudentNumber.CREATOR) ;
		this.notify = (in.readInt() == NOTIFY_TRUE) ;
		
	}
	
	public void setResources(Resource[] resources) {
		StringBuilder ressBuilder = new StringBuilder() ;
		StringBuilder snBuilder = new StringBuilder() ;
		for(Resource res : resources) {
			if (res instanceof StudentNumber) {
				snBuilder.append(RESOURCE_SEPARATOR) ;
				snBuilder.append(((StudentNumber) res).getStudentNumber()) ;
			} else {
				ressBuilder.append(RESOURCE_SEPARATOR) ;
				ressBuilder.append(res.getResource()) ;
			}
		}// for
		if (ressBuilder.length() > 0) {
			ressBuilder.delete(0, RESOURCE_SEPARATOR.length()) ;
		}// if
		if (snBuilder.length() > 0) {
			snBuilder.delete(0, RESOURCE_SEPARATOR.length()) ;
		}// if
//		Log.d("Schedule", String.format("Creating with values:\nRessources: %s\nReal ress: %s\nStudent: %s",
//				Arrays.toString(resources), ressBuilder, snBuilder)) ;
		this.resources = ressBuilder.toString() ;
		this.studentNum = snBuilder.toString() ;
	}// setResources(Resource[])
	
	/**
	 * @return the id
	 */
	public long getId() {
		return this.id;
	}
	
	/**
	 * @param id the id to set
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * Positionne le champ created à la valeur donnée en paramètre.
	 * @param created date de création de l'emploi du temps
	 */
	public void setCreated(String created) {
		this.created = created;
	}

	/**
	 * Positionne le champ lastmodif à la valeur donnée en paramètre.
	 * @param lastModif date de dernière mise à jour
	 */
	public void setLastUpdate(String lastModif) {
		this.lastUpdate = lastModif;
	}

	/**
	 * Positionne le champ name à la valeur donnée en paramètre.
	 * @param name nom de l'emploi du temps
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Positionne le champ status à la valeur donnée en paramètre.
	 * @param status entier representant le statut de synchronisation (non synchro, en attente de synchro, en synchronisation, synchronisé)
	 */
	public void setState(ScheduleState state) {
		this.state = state;
	}

	/**
	 * Positionne le champ period à la valeur donnée en paramètre.
	 * @param period Période pour laquelle synchroniser l'emploi du temps
	 */
	public void setPeriod(int period) {
		this.period = period;
	}

	/**
	 * Positionne le champ projectId à la valeur donnée en paramètre.
	 * @param project Projet AdeWeb identifiant une partie de l'Université de Lorraine
	 */
	public void setProject(Project project) {
		this.project = project;
	}

	/**
	 * Positionne le champ ressources à la valeur donnée en paramètre.
	 * @param resources Numéro de ressources donnée par l'utilisateur
	 */
	public void setResources(String resources) {
		this.resources = resources;
	}

	/**
	 * Positionne le champ studentNum à la valeur donnée en paramètre.
	 * @param studentNum Numéro(s) étudiant donnée(s) par l'utilisateur
	 */
	public void setStudentNum(String studentNum) {
		this.studentNum = studentNum;
	}

	/**
	 * Retourne la valeur du champs created.
	 * @return date de création de l'emploi du temps
	 */
	public String getCreated() {
		return this.created;
	}

	/**
	 * Retourne la valeur du champs lastModif.
	 * @return date de la dernière mise à jour
	 */
	public String getLastUpdate() {
		return this.lastUpdate;
	}

	/**
	 * Retourne la valeur du champs name.
	 * @return Nom de l'emploi du temps
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Retourne la valeur du champs status.
	 * @return Entier representant le statut de synchronisation (non synchro, en attente de synchro, en synchronisation, synchronisé)
	 */
	public ScheduleState getState() {
		return this.state;
	}

	/**
	 * Retourne la valeur du champs period.
	 * @return Période pour laquelle synchroniser l'emploi du temps
	 */
	public int getPeriod() {
		return this.period;
	}
	
	/**
	 * @return the notify
	 */
	public boolean isNotify() {
		return this.notify;
	}
	
	/**
	 * @param notify the notify to set
	 */
	public void setNotify(boolean notify) {
		this.notify = notify;
	}

	/**
	 * Retourne la valeur du champs projectId.
	 * @return Projet AdeWeb identifiant une partie de l'Université de Lorraine
	 */
	public Project getProject() {
		return this.project;
	}

	/**
	 * Retourne la valeur du champs studentNum.
	 * @return Numéro(s) étudiant donnée(s) par l'utilisateur
	 */
	public String getStudentNum(){
		return this.studentNum;
	}

	/**
	 * Retourne la liste de numéros étudiants de l'emploi du temps.
	 * @return 
	 */
	public ArrayList<StudentNumber> getStudentNumList() {
		return this.studentNumList;
	}

	/**
	 * Construit la liste de <code>StudentNumber</code> avec les numéros de ressources associés au(x) numéro(s) étudiant obtenu grâce à l'API ADEWEB.
	 */
	public void setStudentNumList() {
		//Connexion à la webAPI
		FeedConnection connexion = null ;
		try {
			connexion = ContainerData.getFeedConnexion();
			if (connexion != null) {
				String sessionId = connexion.getId() ;
				//Selection du projet
				connexion = ContainerData.getFeedSetProject(
						sessionId, this.project.getAdeProjectId()) ;

				//Cas d'un seul numéro étudiant
				if(!this.studentNum.equals("") && !this.studentNum.contains("|")){ //$NON-NLS-1$ //$NON-NLS-2$
					StudentNumber s = new StudentNumber();
					s.setStudentNumber(this.studentNum);
					//Récupération des ressources associées à un numéro étudiant
					ArrayList<FeedResourceEtud> resNum = ContainerData.getFeedsResources(sessionId,this.studentNum) ;
					for(FeedResourceEtud r : resNum){
						s.addRessource(r.getId());
					}
					this.studentNumList.add(s);

				} else {
					for(String sn :this.studentNum.split("\\|")){ //$NON-NLS-1$
						StudentNumber s = new StudentNumber();
						s.setStudentNumber(sn);
						//Récupération des ressources associées à un numéro étudiant
						ArrayList<FeedResourceEtud> resNum = ContainerData.getFeedsResources(sessionId,sn) ;
						for(FeedResourceEtud r : resNum){
							s.addRessource(r.getId());
						}
						this.studentNumList.add(s);
					}
				}
				StringBuilder sn = new StringBuilder();
				for(StudentNumber s : this.studentNumList){
					if(!sn.toString().equals("")) //$NON-NLS-1$
						sn.append("|"); //$NON-NLS-1$
					sn.append(s.getResources());
				}
				this.ressStudentNum = sn.toString();
//				Log.d("Schedule", "Resources: " + this.resources) ;
//				Log.d("Schedule", "Fetched resources: " + this.ressStudentNum) ;

				//Deconnexion de la webAPI
				connexion = ContainerData.getFeedDeconnexion(sessionId);
			}
		} catch (AAAException e) {
			Log.d(TAG, "Failed to retrieve resources for student number.", e) ; //$NON-NLS-1$
		}// try
	}

	/**
	 * Construit et fixe la chaine de caractères de ressources obtenu depuis les numéros étudiants.
	 */
	public void setStudentNum() {
		String res =""; //$NON-NLS-1$
		if (!this.studentNum.equals("")) { //$NON-NLS-1$
			StringBuilder s = new StringBuilder();
			Database db = MyApplication.getDatabase() ;
			String[] studNum = this.studentNum.split("\\|"); //$NON-NLS-1$
			for(String sn : studNum) {
				s.append(db.getRessourceWithStudentNumber(sn));
			}
			res = s.toString();
		}
		this.ressStudentNum = res;
	}
	/**
	 * Retourne une chaine contenant l'ensemble des ressources données par l'utilisateur et obtenu à partir de numéro(s) étudiant.
	 * @return chaine contenant l'ensemble des ressources données par l'utilisateur et obtenu à partir de numéro(s) étudiant
	 */
	public String getAllResources(){
		StringBuilder s = new StringBuilder(""); //$NON-NLS-1$
		if(!this.resources.equals("") && !this.ressStudentNum.equals("")){ //$NON-NLS-1$ //$NON-NLS-2$
			s.append(this.resources);
			s.append("|"); //$NON-NLS-1$
			s.append(this.ressStudentNum);
		}else if(this.resources.equals("")){ //$NON-NLS-1$
			s.append(this.ressStudentNum);
		}else if(this.ressStudentNum.equals("")){ //$NON-NLS-1$
			s.append(this.resources);
		}
		return s.toString();
	}

	/**
	 * Retourne la valeur du champ ressources.
	 * @return Numéro de ressources donnée par l'utilisateur
	 */
	public String getResources() {
		return this.resources ;
	}// getRessources()

	/**
	 * Retourne une chaine contenant la valeur des différents champs.
	 * Sous la forme : "--------------------\nId : %s\nNom : '%s'\n" +
			"ProjectID : '%s'\nRessources : '%s'\nNuméro étudiant : '%s'\nPériode : '%s'\nDer modif : '%s'\n" +
			"Crée le : '%s'\n--------------------"
	 * 
	 * @return chaine contenant la valeur des différents champs
	 */
	@Override
	public String toString(){
		return String.format(Schedule.STRING_DISPLAY_FORMAT, 
				Long.valueOf(this.id), this.name, this.project, this.resources,this.studentNum, 
				Integer.valueOf(this.period), this.lastUpdate, this.created, this.state,
				Boolean.valueOf(this.notify)) ;
	}// toString()

	/**
	 * Permet de contrôler les informations entrées par l'utilisateur.
	 * <ul><li>Chaque nom d'emploi du temps doit être unique</li>
	 * <li>Aucun champ doit être vide</li>
	 * <li>Verifier le format des ressources</li></ul>
	 * 
	 * @param db Instance de la Base de Données pour un contexte
	 * @throws AAAException 
	 */
	public void validate(Database db) throws AAAException {
		// ------------------------------------------------------------------------------------------------------
		// Check that no field is empty
		// ------------------------------------------------------------------------------------------------------
		if (this.name.equals("")) { //$NON-NLS-1$
			throw new EmptyFieldException("Pas de nom donné pour l'emploi du temps.") ; //$NON-NLS-1$
		}// if
		if (this.resources.equals("") && this.studentNum.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
			throw new EmptyFieldException("Pas de ressources ou pas de numéro etudiant données pour l'emploi du temps.") ; //$NON-NLS-1$
		}// if
		if (this.project == null) {
			throw new EmptyFieldException("Projet manquant.") ; //$NON-NLS-1$
		}// if
		if (this.created.equals("")) { //$NON-NLS-1$
			throw new AAAInternalException("Date de création manquante.") ; //$NON-NLS-1$
		}// if
		if (this.lastUpdate.equals("")) { //$NON-NLS-1$
			throw new AAAInternalException("Date de dernière modification manquante.") ; //$NON-NLS-1$
		}// if

		// ------------------------------------------------------------------------------------------------------
		// Check the given values
		// ------------------------------------------------------------------------------------------------------
		// The projectId can only have limited values
//		if (Arrays.binarySearch(Schedule.VALID_PROJECT_IDS, this.projectId) < 0) {
//			throw new InvalidValueException("Veuillez choisir un établissement valide.") ; //$NON-NLS-1$
//		}// if
		// The name has to be unique and is limited in size
		if (this.name.length() > NAME_MAX_LENGTH) {
			throw new InvalidValueException("Le nom pour l'emploi du temps est trop long.") ; //$NON-NLS-1$
		}// if

		for(Schedule schedule : db.getAllSchedules()) {
			if (schedule.getName().equals(this.name) && schedule.getId() != this.id) {
				throw new InvalidValueException("Il existe déjà un emploi du temps avec ce nom.") ; //$NON-NLS-1$
			}// if
		}// for
		// The ressources can only have the folloing format
		if (!this.resources.equals("") && !this.resources.matches(Schedule.RESSOURCES_FORMAT)) { //$NON-NLS-1$
			throw new InvalidValueException("Les ressources doivent avoir l'un des formats suivants g suivi de chiffres ou juste des chiffres.") ; //$NON-NLS-1$
		}// if
	}// validate()

	/**
	 * Permet de contrôler les informations entrées par l'utilisateur, lors d'une mise à jour d'un emploi du temps.
	 * Mêmes contrôles que la fonction {@link #validate(ade.database.Database)  validate()}, mais permet de changer le nom de l'emploi du temps.
	 * @throws AAAException 
	 */
	public void validateOnUpdate() throws AAAException {
		// ------------------------------------------------------------------------------------------------------
		// Check that no field is empty
		// ------------------------------------------------------------------------------------------------------
		if (this.resources.equals("") && this.studentNum.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
			throw new EmptyFieldException("Pas de ressources ou pas de numéro etudiant données pour l'emploi du temps.") ; //$NON-NLS-1$
		}// if
		if (this.created.equals("")) { //$NON-NLS-1$
			throw new AAAInternalException("Date de création manquante.") ; //$NON-NLS-1$
		}// if
		if (this.lastUpdate.equals("")) { //$NON-NLS-1$
			throw new AAAInternalException("Date de dernière modification manquante.") ; //$NON-NLS-1$
		}// if

		// ------------------------------------------------------------------------------------------------------
		// Check the given values
		// ------------------------------------------------------------------------------------------------------
		// The projectId can only have limited values
//		if (Arrays.binarySearch(Schedule.VALID_PROJECT_IDS, this.projectId) < 0) {
//			throw new InvalidValueException("Veuillez choisir un établissement valide.") ; //$NON-NLS-1$
//		}// if
		// The ressources can only have the folloing format
		if (!this.resources.equals("") && !this.resources.matches(Schedule.RESSOURCES_FORMAT)) { //$NON-NLS-1$
			throw new InvalidValueException("Les ressources doivent avoir l'un des formats suivants g suivi de chiffres ou juste des chiffres.") ; //$NON-NLS-1$
		}// if
	}//validateOnUpdate()

	/**
	 * Construction des cours, récupération depuis l'API.
	 * @throws AAAException 
	 */
	public void build() throws AAAException {
		//Connexion à la webAPI
		FeedConnection connexion = ContainerData.getFeedConnexion();
		if (connexion != null) {                   
			String sessionId = connexion.getId();
			//Selection du projet
			connexion = ContainerData.getFeedSetProject(
					sessionId, this.project.getAdeProjectId()) ;
			//Obtention des cours
			//Instancie la liste de StudentNumber d'un emploi du temps à partie du champs studentNum
			//this.setStudentNumList(sessionId);

			ArrayList<FeedLesson> feedLessons = ContainerData.getFeedsLesson(
					sessionId, this.getAllResources(), this.period) ;   
			// Analyse the feeds and build this instance of Schedule
			FeedAnalyzer fa = new FeedAnalyzer(this, feedLessons) ;
			fa.start() ;
			//Decoonnexion de la webAPI
			connexion = ContainerData.getFeedDeconnexion(sessionId) ;
		}
		else {
			throw new AAAException();
		}

	}// build()

	/**
	 * Construction des cours.
	 * @param db Base de Données
	 */
	public void build(Database db) {
		Lesson[] tabLessons = db.getAllScheduleLessons(this.id) ;
		this.ensureCapacity(tabLessons.length) ;
		for (Lesson l :tabLessons){
			this.append(l);
		}
		/*Cursor lessonsCursor = db.getLessonsCursor(this) ;
		this.ensureCapacity(lessonsCursor.getCount()) ;
		Lesson lesson = Database.cursorToLesson(lessonsCursor) ;
		while (lesson != null) {
			this.append(lesson) ;
			lesson = Database.cursorToLesson(lessonsCursor) ;
		}// while
		lessonsCursor.close() ;*/
//		db.close() ;
	}// build()

	/**
	 * Construction des cours.
	 * @param db Base de Données
	 */
	public void buildComplete(Database db) {
		Lesson[] scheduleLessons = db.getAllScheduleLessons(this.id) ;
		this.ensureCapacity(scheduleLessons.length) ;
		for(Lesson lesson : scheduleLessons) {
			this.append(lesson) ;
		}// for
	}// build()

	/**
	 * Insert un cours dans la liste de cours.
	 * @param l cours
	 */
	public void insert(Lesson l) {
		this.lessons.insert(l) ;
	}// add(Lesson)

	/**
	 * Augmente la capacité du tableau de <code>Lesson</code>.
	 * @param size taille du tableau
	 */
	public void ensureCapacity(int size) {
		this.lessons.ensureCapacity(size) ;
	}// ensureCapacity(int) ;

	/**
	 * Permet d'itérer sur le type <code>Lesson</code>.
	 * @return <code>Iterator<Lesson></code>
	 */
	@Override
	public Iterator<Lesson> iterator() {
		return new Iterator<Lesson>() {
			int next = 0 ;

			@Override
			public boolean hasNext() {
				return (this.next < Schedule.this.lessons.size()) ;
			}// hasNext()

			@Override
			public Lesson next() {
				return Schedule.this.get(this.next++) ;
			}// next()

			@Override
			public void remove() {
				throw new UnsupportedOperationException("ScheduleIterator.remove n'a pas été implanté.") ; //$NON-NLS-1$
			}
		} ;
	}// iterator()

	/**
	 * Retourne un cours de la liste à l'indice donné en paramètre.
	 * @param i
	 * @return le cours
	 */
	protected Lesson get(int i) {
		return this.lessons.get(i) ;
	}// get(int)

	/**
	 * Retroune la liste des cours.
	 * @return les cours
	 */
	public Lessons getLessons() {
		return this.lessons;
	}

	/**
	 * Ajoute un cours à la suite de la liste.
	 * @param l cours
	 */
	public void append(Lesson l) {
		this.lessons.append(l) ;
	}// append(Lesson)

	/**
	 * Retourne la taille du tableau de cours.
	 * @return 
	 */
	public int getNLessons() {
		return this.lessons.size() ;
	}// getNLessons()
	
	

	/**
	 * Fonction de comparaison de 2 Objets <code>Lesson</code>.
	 * @param o
	 * @return vrai si les champs des cours sont identiques, faux sinon
	 */
	@Override
	public boolean equals(Object o) {
		if (o instanceof Schedule) {
			Schedule other = (Schedule) o ;
			return this.name.equals(other.name) && this.resources.equals(other.resources) && (this.studentNum.equals(other.studentNum))
					&& (this.project.equals(other.project)) && (this.period == other.period) ;
		}// if
		return super.equals(o) ;
	}// equals(Object)
	
	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return this.name.hashCode() ;
	}//  hashCode()

	@Override
	public int describeContents() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
	 */
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeLong(this.id) ;
		dest.writeParcelable(this.project, 0) ;
		dest.writeString(this.name) ;
		dest.writeString(this.resources) ;
		dest.writeInt(this.period) ;
		dest.writeString(this.lastUpdate) ;
		dest.writeParcelable(this.state, 0) ;
		dest.writeString(this.created) ;
		dest.writeParcelable(this.lessons, 0) ;
		dest.writeString(this.studentNum) ;
		dest.writeString(this.ressStudentNum) ;
		dest.writeTypedList(this.studentNumList) ;
		dest.writeInt(this.notify ? NOTIFY_TRUE : NOTIFY_FALSE) ;
	}
	
	public static final Parcelable.Creator<Schedule> CREATOR = new Creator<Schedule>() {
		
		@Override
		public Schedule[] newArray(int size) {
			return new Schedule[size] ;
		}
		
		@Override
		public Schedule createFromParcel(Parcel source) {
			return new Schedule(source) ;
		}
	};
}// class Schedule
